# -*- coding: utf-8 -*-
# created on 2016/11/7

from sympy import simplify, expand, degree, latex
from sympy.abc import a, b, c, x, f, g
from sympy.core.function import UndefinedFunction

from mathsolver.functions.base.base import BaseFunction
from mathsolver.functions.base.objects import BaseFunc, BaseEqs
from mathsolver.functions.hanshu.base import solve_extracted_eqs, extract_eqs
from mathsolver.functions.root.jiefangchenzu import JieFangChenZu
from mathsolver.functions.sympy_utils import get_all_child


class DaiDingXiShuQiuJieXiShiYiCi(BaseFunction):
    def solver(self, *args):
        """待定系数法求函数解析式 - 一次函数"""
        if len(args) == 1:
            f1, f2 = args[0].sympify()
            funcs = get_all_child(f1 - f2, lambda xx: isinstance(type(xx), UndefinedFunction))
            self.steps.append(["设f(x)=ax+b(a≠0)，", "则"])
            expr = 0
            for item in funcs:
                this_x = a * x + b if item.args[0] == f(x) else item.args[0]
                expr += f1.coeff(item) * (a * this_x + b)
            expr_sim = simplify(expand(expr))
            self.steps.append(
                ["{}={}={}".format(latex(f1), latex(expr), latex(expr_sim)), ""])
            self.steps.append(["即{}={}不论x为何值都成立".format(latex(expr_sim), latex(f2)), ""])
            eqs = BaseEqs([[expr_sim.coeff(x), f2.coeff(x)],
                           [simplify(expr_sim - expr_sim.coeff(x) * x), simplify(f2 - f2.coeff(x) * x)]])
            self.steps.append(["∴ " + eqs.printing(), ""])
            jiede = JieFangChenZu().solver(eqs)
            self.steps.append(["解得", ""])
            self.steps += jiede.steps
            self.output += jiede.output
            jiede = jiede.output[0]
            # 输出解析式
        elif len(args) == 2:
            f1, f2 = args[1].sympify()
            funcs = get_all_child(f1 - f2, lambda xx: isinstance(type(xx), UndefinedFunction))
            self.steps.append(["设g(x)=ax+b(a≠0)，", ""])
            expr = 0
            for item in funcs:
                if item.args[0].has(g(x)):
                    expr += f1.coeff(item) * (args[0].expression.subs(x, a * x + b + (item.args[0] - g(x))))
                else:
                    expr += f1.coeff(item) * (a * item.args[0] + b)
            expr_exp = expand(expr)
            self.steps.append(["由{0}={1}可得，{2}={1}".format(latex(f1), latex(f2), latex(expr_exp)), ""])
            eqlist = []
            expr = expr_exp
            f2_left = f2
            for i in range(degree(expr_exp, x) + 1)[:0:-1]:
                if expr_exp.coeff(x ** i) != 0:
                    eqlist.append([str(simplify(expr_exp.coeff(x ** i))), str(simplify(f2.coeff(x ** i)))])
                    expr -= expr_exp.coeff(x ** i) * x ** i
                    f2_left -= f2.coeff(x ** i) * x ** i
            eqlist.append([str(simplify(expr)), str(simplify(f2_left))])
            eqs = BaseEqs(eqlist)
            self.steps.append(["即{}".format(eqs.printing()), ""])
            try:
                jiede = JieFangChenZu().solver(eqs)
                self.steps.append(["解得" + jiede.output[0].printing(), ""])
                self.output += jiede.output
                jiede = jiede.output[0]
            except Exception:
                jiede = solve_extracted_eqs(extract_eqs(eqs))
                self.steps.append(["解得" + jiede.printing(), ""])
                self.output.append(jiede)
        key = jiede.value.keys()[0]
        ll = len(jiede.value[key].args)
        if ll > 1:  # 多种解情况
            for i in range(ll):
                new_map = {k: v.args[i] for k, v in jiede.value.items()}
                self.output.append(BaseFunc({'name': 'f', 'var': 'x', 'type': '',
                                             'expression': (a * x + b).subs(new_map)}))
        else:
            self.output.append(BaseFunc({'name': 'f', 'var': 'x', 'type': '',
                                         'expression': (a * x + b).subs(jiede.value)}))
        self.label.add("待定系数法求函数解析式")
        return self


class DaiDingXiShuQiuJieXiShiErCi(BaseFunction):
    def solver(self, *args):
        """待定系数法求函数解析式 - 二次函数"""
        if len(args) == 1:
            f1, f2 = args[0].sympify()
            funcs = get_all_child(f1 - f2, lambda xx: isinstance(type(xx), UndefinedFunction))
            self.steps.append(["设f(x)=ax^{2}+bx+c(a≠0)，", ""])
            expr = 0
            for item in funcs:
                this_x = item.args[0].coeff(f(x)) * (a * x ** 2 + b * x + c) if item.args[0].has(f(x)) else item.args[0]
                expr += f1.coeff(item) * (a * this_x ** 2 + b * this_x + c)
            expr_sim = simplify(expand(expr))
            self.steps.append(["{}={}={}".format(latex(f1), latex(expr), latex(expr_sim)), ""])
            self.steps.append(["即{}={}不论x为何值都成立".format(latex(expr_sim), latex(f2)), ""])
            eqs = BaseEqs([[expr_sim.coeff(x ** 2), f2.coeff(x ** 2)], [expr_sim.coeff(x), f2.coeff(x)],
                           [simplify(expr_sim - expr_sim.coeff(x ** 2) * x ** 2 - expr_sim.coeff(x) * x),
                            simplify(f2 - f2.coeff(x ** 2) * x ** 2 - f2.coeff(x) * x)]])
            self.steps.append(["∴ " + eqs.printing(), ""])
            jiede = JieFangChenZu().solver(eqs)
            self.steps.append(["解得", ""])
            self.steps += jiede.steps
            self.output += jiede.output
            jiede = jiede.output[0]
        elif len(args) == 2:
            p_x, p_y = args[0].sympify()
            f1, f2 = args[1].sympify()
            funcs = get_all_child(f1 - f2, lambda xx: isinstance(type(xx), UndefinedFunction))
            self.steps.append(["设f(x)=ax^{2}+bx+c(a≠0)，", ""])
            expr = 0
            for item in funcs:
                this_x = item.args[0].coeff(f(x)) * (a * x ** 2 + b * x + c) if item.args[0].has(f(x)) else item.args[0]
                expr += f1.coeff(item) * (a * this_x ** 2 + b * this_x + c)
            expr_exp = expand(expr)
            self.steps.append(["由{0}={1}可得，{2}={1}".format(latex(f1), latex(f2), latex(expr_exp)), ""])
            eqlist = []
            expr = expr_exp
            f2_left = f2
            for i in range(degree(expr_exp, x) + 1)[:0:-1]:
                if expr_exp.coeff(x ** i) != 0:
                    eqlist.append([str(expr_exp.coeff(x ** i)), str(f2.coeff(x ** i))])
                    expr -= expr_exp.coeff(x ** i) * x ** i
                    f2_left -= f2.coeff(x ** i) * x ** i
            eqlist.append([str(simplify(expr)), str(f2_left)])
            if p_x.is_Add:
                p_list = [item.args[0] for item in p_x.args]
                expr = a * x ** 2 + b * x + c
                p_subs = 0
                for item in p_list:
                    p_subs += expr.subs(x, item)
            else:
                p_subs = (a * x ** 2 + b * x + c).subs(x, p_x.args[0])
            if p_subs is not None:
                eqlist.append([str(simplify(p_subs)), str(p_y)])
            eqs = BaseEqs(eqlist)
            self.steps.append(["即{}".format(eqs.printing()), ""])
            try:
                jiede = JieFangChenZu().solver(eqs)
                # self.steps.append(["解得" + eqs.printing(), ""])
                self.steps.append(["解得" + jiede.output[0].printing(), ""])
                self.output += jiede.output
                jiede = jiede.output[0]
            except Exception:
                jiede = solve_extracted_eqs(extract_eqs(eqs))
                self.steps.append(["解得" + jiede.printing(), ""])
                self.output.append(jiede)
        key = jiede.value.keys()[0]
        ll = len(jiede.value[key].args)
        if ll > 1:  # 多种解情况
            for i in range(ll):
                new_map = {k: v.args[i] for k, v in jiede.value.items()}
                self.output.append(BaseFunc({'name': 'f', 'var': 'x', 'type': '',
                                             'expression': (a * x + b).subs(new_map)}))
        else:
            self.output.append(BaseFunc({'name': 'f', 'var': 'x', 'type': '',
                                         'expression': (a * x + b).subs(jiede.value)}))
        self.label.add("待定系数法求函数解析式")
        return self


if __name__ == '__main__':
    pass
